package com.shlh.saas.service.impl;

import com.alipay.api.kms.aliyun.exceptions.ClientException;
import com.microsoft.aad.msal4j.ClientCredentialFactory;
import com.microsoft.aad.msal4j.ClientCredentialParameters;
import com.microsoft.aad.msal4j.ConfidentialClientApplication;
import com.microsoft.aad.msal4j.IAuthenticationResult;
import com.microsoft.graph.authentication.IAuthenticationProvider;
import com.microsoft.graph.models.User;
import com.microsoft.graph.requests.GraphServiceClient;
import com.shlh.saas.common.Result;
import com.shlh.saas.common.UserContext;
import com.shlh.saas.entity.UserEmail;
import com.shlh.saas.model.dto.EmailVerificationDTO;
import com.shlh.saas.service.EmailService;
import com.shlh.saas.service.EmailVerificationService;
import jakarta.mail.AuthenticationFailedException;
import jakarta.mail.MessagingException;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import okhttp3.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.*;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.regex.Pattern;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

/**
 * 邮箱验证服务实现类
 */
@Service
public class EmailVerificationServiceImpl implements EmailVerificationService {

    private static final Logger log = LoggerFactory.getLogger(EmailVerificationServiceImpl.class);

    @Autowired
    private EmailService emailService;

    // 定义常用邮箱的域名正则表达式
    private static final Pattern QQ_EMAIL = Pattern.compile("^[a-zA-Z0-9_-]+@qq\\.com$");
    private static final Pattern EMAIL_163 = Pattern.compile("^[a-zA-Z0-9_-]+@163\\.com$");
    private static final Pattern EMAIL_126 = Pattern.compile("^[a-zA-Z0-9_-]+@126\\.com$");
    private static final Pattern EMAIL_SINA = Pattern.compile("^[a-zA-Z0-9_-]+@(sina\\.com|sina\\.cn)$");
    private static final Pattern EMAIL_GMAIL = Pattern.compile("^[a-zA-Z0-9_-]+@gmail\\.com$");
    private static final Pattern EMAIL_OUTLOOK = Pattern.compile("^[a-zA-Z0-9_-]+@(outlook\\.com|hotmail\\.com)$");
    private static final Pattern EMAIL_YAHOO = Pattern.compile("^[a-zA-Z0-9_-]+@yahoo\\.com$");

    @Override
    public Result<Boolean> verifyEmailCredentials(EmailVerificationDTO emailVerificationDTO) {
        String email = emailVerificationDTO.getEmailAddress();
        String authCode = emailVerificationDTO.getAuthCode();
        String emailProvider = emailVerificationDTO.getEmailProvider(); // 获取前端传递的邮箱发行商信息

        if (email == null || email.trim().isEmpty() || authCode == null || authCode.trim().isEmpty()) {
            return Result.error("邮箱地址或授权码不能为空");
        }

        // 记录开始验证的邮箱类型
        if (EMAIL_163.matcher(email).matches() || "163".equals(emailProvider)) {
            log.info("开始验证163邮箱: {}", email);
        } else if (EMAIL_126.matcher(email).matches() || "126".equals(emailProvider)) {
            log.info("开始验证126邮箱: {}", email);
        } else if (QQ_EMAIL.matcher(email).matches() || "qq".equals(emailProvider)) {
            log.info("开始验证QQ邮箱: {}", email);
        } else if (EMAIL_GMAIL.matcher(email).matches() || "gmail".equals(emailProvider)) {
            log.info("开始验证Gmail邮箱: {}, 请确保已开启'允许不够安全的应用访问'或使用应用专用密码", email);
        } else if (EMAIL_SINA.matcher(email).matches() || "sina".equals(emailProvider)) {
            log.info("开始验证新浪邮箱: {}, 请确保已开启SMTP服务并使用正确的授权码", email);
        } else if (EMAIL_YAHOO.matcher(email).matches() || "yahoo".equals(emailProvider)) {
            log.info("开始验证Yahoo邮箱: {}, 请确保已开启SMTP服务并使用应用专用密码", email);
        } else if ("outlook".equals(emailProvider)) {
            log.info("开始验证Outlook邮箱: {}", email);
        } else {
            log.info("开始验证邮箱: {}", email);
        }

        // 根据邮箱域名或发行商信息获取SMTP配置
        EmailServerConfig config = getEmailServerConfigByProvider(email, emailProvider);
        if (config == null) {
            return Result.error("不支持的邮箱类型");
        }

        // 验证邮箱和授权码是否有效
        try {
            // 标准SMTP验证
            boolean isValid = tryMultipleConfigurations(email, authCode, config, emailProvider);
            if (isValid) {
                boolean saved = emailService.saveEmailRecord(email, authCode, 1, emailProvider);
                if (!saved) {
                    return Result.error("保存邮箱验证结果失败");
                }
                return Result.success(true, "邮箱验证成功");
            } else {
                emailService.saveEmailRecord(email, authCode, 0, emailProvider);
                return Result.error("邮箱验证失败，请检查邮箱地址和授权码");
            }
        } catch (AuthenticationFailedException e) {
            log.error("邮箱认证失败: {}", e.getMessage());
            emailService.saveEmailRecord(email, authCode, 0, emailProvider);

            // Gmail特殊错误处理
            if (EMAIL_GMAIL.matcher(email).matches() || "gmail".equals(emailProvider)) {
                if (e.getMessage() != null && e.getMessage().contains("Username and Password not accepted")) {
                    return Result.error("Gmail验证失败: 用户名和密码不正确。请使用应用专用密码，或在Google账户中开启'允许不够安全的应用访问'");
                } else if (e.getMessage() != null && e.getMessage().contains("534-5.7.14")) {
                    return Result.error("Gmail验证失败: 需要使用应用专用密码。请前往 https://myaccount.google.com/apppasswords 生成应用专用密码");
                } else if (e.getMessage() != null && e.getMessage().contains("535-5.7.8")) {
                    return Result.error("Gmail验证失败: 需要开启'允许不够安全的应用访问'或使用应用专用密码");
                }
            }

            // 新浪邮箱特殊错误处理
            if (EMAIL_SINA.matcher(email).matches() || "sina".equals(emailProvider)) {
                if (e.getMessage() != null && e.getMessage().contains("Invalid credentials")) {
                    return Result.error("新浪邮箱验证失败: 授权码不正确。请确保您已在新浪邮箱设置中开启SMTP服务并获取正确的授权码");
                } else if (e.getMessage() != null && e.getMessage().contains("Authentication failed")) {
                    return Result.error("新浪邮箱验证失败: 认证失败。请确保使用的是授权码而非登录密码");
                }
            }

            // Yahoo邮箱特殊错误处理
            if (EMAIL_YAHOO.matcher(email).matches() || "yahoo".equals(emailProvider)) {
                if (e.getMessage() != null && e.getMessage().contains("Invalid credentials")) {
                    return Result.error("Yahoo邮箱验证失败: 应用专用密码不正确。请确保您已在Yahoo账户设置中生成正确的应用专用密码");
                } else if (e.getMessage() != null && e.getMessage().contains("Authentication failed")) {
                    return Result.error("Yahoo邮箱验证失败: 认证失败。请确保使用的是应用专用密码而非登录密码");
                } else if (e.getMessage() != null && e.getMessage().contains("not permitted")) {
                    return Result.error("Yahoo邮箱验证失败: 需要开启'允许安全性较低的应用访问'选项或使用应用专用密码");
                }
            }

            return Result.error("邮箱或授权码错误");
        } catch (MessagingException e) {
            log.error("连接邮箱服务器失败: {}", e.getMessage());
            emailService.saveEmailRecord(email, authCode, 0, emailProvider);

            // Gmail特殊错误处理
            if (EMAIL_GMAIL.matcher(email).matches() || "gmail".equals(emailProvider)) {
                return Result.error("Gmail连接失败: 请确保网络环境可以访问Google服务，或尝试使用代理");
            }

            // 新浪邮箱特殊错误处理
            if (EMAIL_SINA.matcher(email).matches() || "sina".equals(emailProvider)) {
                if (e.getMessage() != null && e.getMessage().contains("Connection refused")) {
                    return Result.error("新浪邮箱连接失败: 连接被拒绝，请确保您的网络环境允许连接到新浪服务器");
                } else if (e.getMessage() != null && e.getMessage().contains("timed out")) {
                    return Result.error("新浪邮箱连接失败: 连接超时，请检查网络状态或尝试其他端口");
                } else if (e.getMessage() != null && e.getMessage().contains("Could not connect")) {
                    return Result.error("新浪邮箱连接失败: 无法连接到服务器，请确保SMTP服务已开启");
                }
                return Result.error("新浪邮箱连接失败: " + e.getMessage());
            }

            // Yahoo邮箱特殊错误处理
            if (EMAIL_YAHOO.matcher(email).matches() || "yahoo".equals(emailProvider)) {
                if (e.getMessage() != null && e.getMessage().contains("Connection refused")) {
                    return Result.error("Yahoo邮箱连接失败: 连接被拒绝，请确保您的网络环境允许连接到Yahoo服务器");
                } else if (e.getMessage() != null && e.getMessage().contains("timed out")) {
                    return Result.error("Yahoo邮箱连接失败: 连接超时，请检查网络状态或尝试其他端口");
                } else if (e.getMessage() != null && e.getMessage().contains("Could not connect")) {
                    return Result.error("Yahoo邮箱连接失败: 无法连接到服务器，请确保SMTP服务已开启");
                }
                return Result.error("Yahoo邮箱连接失败: " + e.getMessage());
            }

            return Result.error("连接邮箱服务器失败：" + e.getMessage());
        } catch (Exception e) {
            log.error("邮箱验证过程中发生错误: {}", e.getMessage());
            emailService.saveEmailRecord(email, authCode, 0, emailProvider);
            return Result.error("验证过程中发生错误：" + e.getMessage());
        }
    }

    @Override
    public boolean verifyOutlookDeviceCode(String emailAddress, String deviceCodeJson) {
        log.info("开始验证Outlook授权: {}", emailAddress);

        try {
            // 解析设备码JSON
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(deviceCodeJson);

            // 获取用户邮箱配置
            UserEmail userEmail = emailService.getUserEmailByUserIdAndEmail(UserContext.getUserId(), emailAddress);

            // 从请求中获取设备码
            String deviceCode = jsonNode.has("deviceCode") ? jsonNode.get("deviceCode").asText() : "";

            // 从用户邮箱配置中获取OAuth信息
            String clientId = userEmail.getClientId();
            String tenantId = userEmail.getTenantId();
            String clientSecret = userEmail.getClientSecret();

            // 如果邮箱密码字段包含JSON数据，尝试从中提取设备码
            if (userEmail.getEmailPassword() != null && userEmail.getEmailPassword().startsWith("{")) {
                try {
                    JsonNode passwordJson = objectMapper.readTree(userEmail.getEmailPassword());
                    // 如果没有设备码或设备码为空，尝试从密码字段中获取
                    if ((deviceCode == null || deviceCode.isEmpty()) && passwordJson.has("deviceCode")) {
                        deviceCode = passwordJson.get("deviceCode").asText();
                    }
                } catch (Exception e) {
                    log.warn("解析邮箱密码JSON失败: {}", e.getMessage());
                }
            }

            log.info("验证设备码授权 - 设备码: {}, 客户端ID: {}, 租户ID: {}",
                    deviceCode.substring(0, Math.min(10, deviceCode.length())) + "...",
                    clientId, tenantId);


            if (deviceCode == null || deviceCode.isEmpty() ||
                    clientId == null || clientId.isEmpty() ||
                    tenantId == null || tenantId.isEmpty()) {
                log.error("设备码授权信息不完整");
                return false;
            }

            // 实际验证设备码授权
            boolean isAuthorized = checkDeviceCodeAuthorization(emailAddress, deviceCode, clientId, tenantId, clientSecret);


            return isAuthorized;
        } catch (Exception e) {
            log.error("验证Outlook设备码授权失败: {}", e.getMessage(), e);
            try {
                emailService.saveEmailRecord(emailAddress, deviceCodeJson, 0, "outlook");
            } catch (Exception ex) {
                log.error("保存设备码授权失败记录时出错: {}", ex.getMessage(), ex);
            }
            return false;
        }
    }

    @Override
    public boolean verifyOutlookToken(String emailAddress) {
        log.info("开始验证Outlook Token，邮箱: {}", emailAddress);

        UserEmail userEmail = emailService.getUserEmailByUserIdAndEmail(UserContext.getUserId(), emailAddress);
        
        if (userEmail == null) {
            log.error("未找到邮箱配置: {}", emailAddress);
            return false;
        }
        
        log.info("找到邮箱配置: id={}, email={}, provider={}", userEmail.getId(), userEmail.getEmail(), userEmail.getEmailProvider());

        String clientId = userEmail.getClientId();
        String clientSecret = userEmail.getClientSecret();
        String tenantId = userEmail.getTenantId();
        String redirectUri = userEmail.getRedirectUri();

        log.info("OAuth配置信息: clientId={}, tenantId={}, redirectUri={}, clientSecret长度={}", 
                clientId, tenantId, redirectUri, 
                clientSecret != null ? clientSecret.length() : 0);

        if (clientId == null || clientId.isEmpty()) {
            log.error("客户端Id为空");
            return false;
        }

        if (clientSecret == null || clientSecret.isEmpty()) {
            log.error("密钥为空");
            return false;
        }

        if (tenantId == null || tenantId.isEmpty()) {
            log.error("租户Id为空");
            return false;
        }

        // 1. 获取访问令牌
        String accessToken;
        try {
            accessToken = getAccessToken(clientId, clientSecret, tenantId);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        // 2. 创建 Graph 客户端
        GraphServiceClient<Request> graphClient = createGraphClient(accessToken);

        // === 新增：验证令牌有效性 ===
        System.out.println("正在验证访问令牌...");
        // 尝试获取用户基本信息（需要 User.Read.All 权限）
        User user = graphClient.users(emailAddress)
                .buildRequest()
                .select("displayName,mail,userPrincipalName")
                .get();

        if (user == null) {
            return false;
        }

        System.out.println("✅ OAuth 认证成功！");
        System.out.println("用户信息: " + user.displayName + " <" + user.mail + ">");
        System.out.println("令牌权限范围: " + user.userPrincipalName);

        // 修改状态
        emailService.saveEmailSuccess(userEmail.getUserId(),userEmail.getEmail(), 1);

        return true;
    }

    private GraphServiceClient<Request> createGraphClient(String accessToken) {
        IAuthenticationProvider authProvider = requestUrl -> CompletableFuture.completedFuture(accessToken);

        return GraphServiceClient.builder()
                .authenticationProvider(authProvider)
                .buildClient();
    }

    private String getAccessToken(String clientId, String clientSecret, String tenantId) throws Exception {
        // 使用新的方式创建客户端凭证
        ConfidentialClientApplication app = ConfidentialClientApplication.builder(
                        clientId,
                        ClientCredentialFactory.createFromSecret(clientSecret)) // 直接使用客户端密钥字符串
                .authority("https://login.microsoftonline.com/" + tenantId + "/")
                .build();

        ClientCredentialParameters parameters = ClientCredentialParameters.builder(
                        Collections.singleton("https://graph.microsoft.com/.default"))
                .build();

        CompletableFuture<IAuthenticationResult> future = app.acquireToken(parameters);
        IAuthenticationResult result = future.get();

        System.out.println("获取访问令牌成功，Token 类型: " + result);
        System.out.println("令牌过期时间: " + result.expiresOnDate());

        return result.accessToken();
    }

    /**
     * 检查设备码授权状态
     *
     * @param deviceCode   设备码
     * @param clientId     客户端ID
     * @param tenantId     租户ID
     * @param clientSecret 客户端密钥（可选）
     * @return 是否已授权
     */
    private boolean checkDeviceCodeAuthorization(String email, String deviceCode, String clientId, String tenantId, String clientSecret) {
        try {
            // 检查必要参数
            if (deviceCode == null || deviceCode.isEmpty()) {
                log.error("设备码为空，无法进行验证");
                return false;
            }

            if (clientId == null || clientId.isEmpty()) {
                log.error("客户端ID为空，无法进行验证");
                return false;
            }

            if (tenantId == null || tenantId.isEmpty()) {
                log.error("租户ID为空，无法进行验证");
                return false;
            }

            // 构建请求URL
            String tokenUrl = "https://login.microsoftonline.com/" + tenantId + "/oauth2/v2.0/token";
            log.info("设备码授权请求URL: {}", tokenUrl);

            // 构建请求参数
            StringBuilder requestBodyBuilder = new StringBuilder();
            requestBodyBuilder.append("grant_type=urn:ietf:params:oauth:grant-type:device_code");
            requestBodyBuilder.append("&client_id=").append(clientId);
            requestBodyBuilder.append("&device_code=").append(deviceCode);

            // 如果有客户端密钥，则添加
            if (clientSecret != null && !clientSecret.isEmpty()) {
                requestBodyBuilder.append("&client_secret=").append(clientSecret);
                log.info("使用客户端密钥进行授权");
            } else {
                log.info("未使用客户端密钥进行授权");
            }

            String requestBody = requestBodyBuilder.toString();
            log.debug("设备码授权请求参数: {}", requestBody.replace(deviceCode, "***DEVICE_CODE***"));

            // 创建HTTP客户端
            URL url = new URL(tokenUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("Accept", "application/json");
            connection.setDoOutput(true);
            connection.setConnectTimeout(10000); // 10秒连接超时
            connection.setReadTimeout(10000);    // 10秒读取超时

            // 发送请求
            try (java.io.OutputStream os = connection.getOutputStream()) {
                byte[] input = requestBody.getBytes("utf-8");
                os.write(input, 0, input.length);
            }

            // 读取响应
            int responseCode = connection.getResponseCode();
            log.info("设备码授权响应码: {}", responseCode);

            // 如果响应码为200，表示授权成功
            if (responseCode == 200) {
                // 解析响应
                StringBuilder response = new StringBuilder();
                try (java.io.BufferedReader br = new java.io.BufferedReader(
                        new java.io.InputStreamReader(connection.getInputStream(), "utf-8"))) {
                    String responseLine;
                    while ((responseLine = br.readLine()) != null) {
                        response.append(responseLine.trim());
                    }
                }

                log.debug("授权成功响应: {}", response.toString());

                // 解析JSON响应
                ObjectMapper mapper = new ObjectMapper();
                JsonNode jsonNode = mapper.readTree(response.toString());

                // 检查是否包含access_token
                boolean hasAccessToken = jsonNode.has("access_token");
                if (!hasAccessToken) {
                    log.error("授权响应中不包含access_token");
                    return false;
                }
                String accessToken = jsonNode.get("access_token").asText();
                String refreshToken = jsonNode.has("refresh_token") ? jsonNode.get("refresh_token").asText() : null;
                int expiresIn = Math.toIntExact(jsonNode.has("expires_in") ? jsonNode.get("expires_in").asLong() : 0);
                LocalDateTime expiry = toExpiry(expiresIn);

                log.info("授权成功，access_token: {}, refresh_token: {}, expires_in: {}秒", accessToken, refreshToken, expiresIn);

                // 保存验证结果
                boolean saved = emailService.saveEmail(UserContext.getUserId(), email, deviceCode, accessToken, refreshToken, expiry);
                if (!saved) {
                    log.error("保存设备码授权结果失败");
                    return false;
                }

                return hasAccessToken;
            } else {
                // 读取错误响应
                StringBuilder errorResponse = new StringBuilder();
                try (java.io.BufferedReader br = new java.io.BufferedReader(
                        new java.io.InputStreamReader(
                                responseCode >= 400 ? connection.getErrorStream() : connection.getInputStream(),
                                "utf-8"))) {
                    String responseLine;
                    while ((responseLine = br.readLine()) != null) {
                        errorResponse.append(responseLine.trim());
                    }
                }

                log.error("授权失败响应: {}", errorResponse.toString());

                // 尝试解析JSON错误响应
                try {
                    ObjectMapper mapper = new ObjectMapper();
                    JsonNode jsonNode = mapper.readTree(errorResponse.toString());

                    // 检查错误代码
                    if (jsonNode.has("error")) {
                        String error = jsonNode.get("error").asText();
                        String errorDescription = jsonNode.has("error_description") ?
                                jsonNode.get("error_description").asText() : "";

                        // "authorization_pending"表示用户尚未完成授权
                        if ("authorization_pending".equals(error)) {
                            log.info("设备码授权尚未完成，等待用户授权: {}", errorDescription);
                            return false;
                        }
                        // "expired_token"表示设备码已过期
                        else if ("expired_token".equals(error)) {
                            log.error("设备码已过期: {}", errorDescription);
                            return false;
                        }
                        // "invalid_client"表示客户端ID无效
                        else if ("invalid_client".equals(error)) {
                            log.error("无效的客户端ID: {}", errorDescription);
                            return false;
                        }
                        // "invalid_grant"表示授权无效
                        else if ("invalid_grant".equals(error)) {
                            log.error("无效的授权: {}", errorDescription);
                            return false;
                        }
                        // 其他错误
                        else {
                            log.error("设备码授权失败: {} - {}", error, errorDescription);
                            return false;
                        }
                    }
                } catch (Exception e) {
                    log.error("解析错误响应失败: {}", e.getMessage());
                }
            }

            log.error("验证设备码授权失败，HTTP响应码: {}", responseCode);
            return false;
        } catch (Exception e) {
            log.error("验证设备码授权时出错: {}", e.getMessage(), e);
            return false;
        }
    }

    public LocalDateTime toExpiry(int expiresInSeconds) {
        Instant now = Instant.now();
        return LocalDateTime.ofInstant(now.plusSeconds(expiresInSeconds - 60), ZoneOffset.UTC);
    }

    /**
     * 尝试多种不同的配置连接邮箱服务器
     *
     * @param email         邮箱地址
     * @param authCode      授权码
     * @param primaryConfig 主要配置
     * @param emailProvider 邮箱发行商标识
     * @return 是否连接成功
     * @throws MessagingException 如果所有配置都连接失败
     */
    private boolean tryMultipleConfigurations(String email, String authCode, EmailServerConfig primaryConfig, String emailProvider) throws MessagingException {
        // 先测试网络连接
        boolean canConnect = testSocketConnection(primaryConfig.getHost(), primaryConfig.getPort(), 5000);
        if (!canConnect) {
            log.warn("无法通过Socket连接到 {}:{}，可能是网络问题", primaryConfig.getHost(), primaryConfig.getPort());
        } else {
            log.info("Socket连接测试成功: {}:{}", primaryConfig.getHost(), primaryConfig.getPort());
        }

        // 首先尝试主要配置
        try {
            return verifyMailServerConnection(email, authCode, primaryConfig, emailProvider);
        } catch (MessagingException e) {
            log.warn("主要配置连接失败: {}, 尝试备用配置...", e.getMessage());
        }

        // 如果主要配置失败，尝试备用配置
        List<EmailServerConfig> backupConfigs = new ArrayList<>();

        // QQ邮箱的备用配置
        if (QQ_EMAIL.matcher(email).matches() || "qq".equals(emailProvider)) {
            // 备用配置1: 端口587 + STARTTLS
            backupConfigs.add(new EmailServerConfig("smtp.qq.com", 587, true, false));
            // 备用配置2: 端口25 + STARTTLS
            backupConfigs.add(new EmailServerConfig("smtp.qq.com", 25, true, false));
            // 备用配置3: 端口995 (SMTP over SSL)
            backupConfigs.add(new EmailServerConfig("smtp.qq.com", 995, false, true));

            // 使用IP地址的备用配置 (QQ邮箱的IP地址可能会变化，这些是当前的IP)
            backupConfigs.add(new EmailServerConfig("183.3.225.43", 465, false, true)); // smtp.qq.com IP地址
            backupConfigs.add(new EmailServerConfig("183.3.225.43", 587, true, false));
        }
        // 163邮箱的备用配置
        else if (EMAIL_163.matcher(email).matches() || "163".equals(emailProvider)) {
            backupConfigs.add(new EmailServerConfig("smtp.163.com", 25, true, false));
            backupConfigs.add(new EmailServerConfig("smtp.163.com", 994, false, true));
            backupConfigs.add(new EmailServerConfig("smtp.163.com", 587, true, false));

            // 使用IP地址的备用配置 (163邮箱的IP地址)
            backupConfigs.add(new EmailServerConfig("220.181.12.11", 465, false, true)); // smtp.163.com IP地址
            backupConfigs.add(new EmailServerConfig("220.181.12.11", 25, true, false));
            backupConfigs.add(new EmailServerConfig("220.181.12.11", 994, false, true));
        }
        // 126邮箱的备用配置
        else if (EMAIL_126.matcher(email).matches() || "126".equals(emailProvider)) {
            backupConfigs.add(new EmailServerConfig("smtp.126.com", 25, true, false));
            backupConfigs.add(new EmailServerConfig("smtp.126.com", 994, false, true));
            backupConfigs.add(new EmailServerConfig("smtp.126.com", 587, true, false));

            // 使用IP地址的备用配置 (126邮箱的IP地址，与163共用)
            backupConfigs.add(new EmailServerConfig("220.181.12.11", 465, false, true));
            backupConfigs.add(new EmailServerConfig("220.181.12.11", 25, true, false));
        }
        // Gmail邮箱的备用配置
        else if (EMAIL_GMAIL.matcher(email).matches() || "gmail".equals(emailProvider)) {
            // 优先使用新的TLS配置（端口587 + TLSv1.2/TLSv1.3）
            backupConfigs.add(new EmailServerConfig("smtp.gmail.com", 587, true, false)); // 优先使用TLS配置

            // 备用配置
            backupConfigs.add(new EmailServerConfig("smtp.gmail.com", 465, false, true));
            backupConfigs.add(new EmailServerConfig("smtp.gmail.com", 25, true, false));

            // 使用IP地址的备用配置 (Gmail的IP地址可能会变化，这些是常用IP)
            backupConfigs.add(new EmailServerConfig("142.250.4.109", 587, true, false));
            backupConfigs.add(new EmailServerConfig("142.250.4.109", 465, false, true));

            // Gmail备用服务器
            backupConfigs.add(new EmailServerConfig("aspmx.l.google.com", 25, true, false));
            backupConfigs.add(new EmailServerConfig("alt1.gmail-smtp-in.l.google.com", 25, true, false));
            backupConfigs.add(new EmailServerConfig("alt2.gmail-smtp-in.l.google.com", 25, true, false));
        }
        // 新浪邮箱的备用配置
        else if (EMAIL_SINA.matcher(email).matches() || "sina".equals(emailProvider)) {
            // 新浪邮箱支持多种端口
            backupConfigs.add(new EmailServerConfig("smtp.sina.com", 25, true, false));
            backupConfigs.add(new EmailServerConfig("smtp.sina.com", 587, true, false));
            backupConfigs.add(new EmailServerConfig("smtp.sina.cn", 465, false, true));
            backupConfigs.add(new EmailServerConfig("smtp.sina.cn", 25, true, false));

            // 新浪企业邮箱
            backupConfigs.add(new EmailServerConfig("smtp.vip.sina.com", 465, false, true));
            backupConfigs.add(new EmailServerConfig("smtp.vip.sina.com", 25, true, false));

            // 使用IP地址的备用配置
            backupConfigs.add(new EmailServerConfig("123.125.50.21", 465, false, true));
            backupConfigs.add(new EmailServerConfig("123.125.50.21", 25, true, false));
        }
        // Yahoo邮箱的备用配置
        else if (EMAIL_YAHOO.matcher(email).matches() || "yahoo".equals(emailProvider)) {
            // Yahoo邮箱支持多种端口
            backupConfigs.add(new EmailServerConfig("smtp.mail.yahoo.com", 465, false, true));
            backupConfigs.add(new EmailServerConfig("smtp.mail.yahoo.com", 25, true, false));
            backupConfigs.add(new EmailServerConfig("smtp.mail.yahoo.com", 587, true, false));

            // Yahoo备用服务器
            backupConfigs.add(new EmailServerConfig("smtp.yahoo.com", 587, true, false));
            backupConfigs.add(new EmailServerConfig("smtp.yahoo.com", 465, false, true));
            backupConfigs.add(new EmailServerConfig("smtp.yahoo.com", 25, true, false));

            // 地区特定服务器
            backupConfigs.add(new EmailServerConfig("smtp.mail.yahoo.co.jp", 587, true, false)); // 日本
            backupConfigs.add(new EmailServerConfig("smtp.mail.yahoo.co.uk", 587, true, false)); // 英国

            // 使用IP地址的备用配置 (Yahoo的IP地址可能会变化)
            backupConfigs.add(new EmailServerConfig("98.136.86.109", 587, true, false));
            backupConfigs.add(new EmailServerConfig("98.136.86.109", 465, false, true));
            backupConfigs.add(new EmailServerConfig("98.136.86.109", 25, true, false));
        }
        // 其他邮箱可以根据需要添加备用配置

        // 尝试所有备用配置
        MessagingException lastException = null;
        for (EmailServerConfig config : backupConfigs) {
            // 先测试网络连接
            canConnect = testSocketConnection(config.getHost(), config.getPort(), 5000);
            if (!canConnect) {
                log.warn("无法通过Socket连接到 {}:{}，跳过此配置", config.getHost(), config.getPort());
                continue;
            }

            try {
                boolean result = verifyMailServerConnection(email, authCode, config, emailProvider);
                if (result) {
                    log.info("使用备用配置连接成功: {}:{}", config.getHost(), config.getPort());
                    return true;
                }
            } catch (MessagingException e) {
                lastException = e;
                log.warn("备用配置连接失败: {}:{}, 错误: {}", config.getHost(), config.getPort(), e.getMessage());
            }
        }

        // 如果所有配置都失败，抛出最后一个异常
        if (lastException != null) {
            throw lastException;
        }

        return false;
    }

    /**
     * 根据邮箱地址获取对应的邮箱服务器配置
     *
     * @param email 邮箱地址
     * @return 邮箱服务器配置
     */
    private EmailServerConfig getEmailServerConfig(String email) {
        // QQ邮箱
        if (QQ_EMAIL.matcher(email).matches()) {
            // QQ邮箱支持多种端口，尝试使用最可靠的SSL端口
            return new EmailServerConfig("smtp.qq.com", 465, false, true);
        }
        // 163邮箱
        else if (EMAIL_163.matcher(email).matches()) {
            return new EmailServerConfig("smtp.163.com", 465, false, true);
        }
        // 126邮箱
        else if (EMAIL_126.matcher(email).matches()) {
            return new EmailServerConfig("smtp.126.com", 465, false, true);
        }
        // 新浪邮箱
        else if (EMAIL_SINA.matcher(email).matches()) {
            return new EmailServerConfig("smtp.sina.com", 465, false, true);
        }
        // Gmail邮箱
        else if (EMAIL_GMAIL.matcher(email).matches()) {
            // 使用端口587 + TLS (STARTTLS)，这是Gmail推荐的配置
            return new EmailServerConfig("smtp.gmail.com", 587, true, false);
        }
        // Outlook/Hotmail邮箱
        else if (EMAIL_OUTLOOK.matcher(email).matches()) {
            return new EmailServerConfig("smtp.office365.com", 587, true, false);
        }
        // Yahoo邮箱
        else if (EMAIL_YAHOO.matcher(email).matches()) {
            return new EmailServerConfig("smtp.mail.yahoo.com", 587, true, false);
        }
        // 其他邮箱类型可以继续扩展

        return null; // 未识别的邮箱类型
    }

    /**
     * 根据邮箱地址和发行商信息获取对应的邮箱服务器配置
     *
     * @param email         邮箱地址
     * @param emailProvider 邮箱发行商标识
     * @return 邮箱服务器配置
     */
    private EmailServerConfig getEmailServerConfigByProvider(String email, String emailProvider) {
        // 优先使用发行商信息
        if (emailProvider != null && !emailProvider.isEmpty()) {
            switch (emailProvider) {
                case "qq":
                    return new EmailServerConfig("smtp.qq.com", 465, false, true);
                case "163":
                    return new EmailServerConfig("smtp.163.com", 465, false, true);
                case "126":
                    return new EmailServerConfig("smtp.126.com", 465, false, true);
                case "sina":
                    return new EmailServerConfig("smtp.sina.com", 465, false, true);
                case "gmail":
                    return new EmailServerConfig("smtp.gmail.com", 587, true, false);
                case "outlook":
                    return new EmailServerConfig("smtp.office365.com", 587, true, false);
                case "yahoo":
                    return new EmailServerConfig("smtp.mail.yahoo.com", 587, true, false);
                default:
                    // 如果是未知的发行商，尝试根据邮箱地址判断
                    break;
            }
        }

        // 如果没有发行商信息或者发行商未知，则根据邮箱地址判断
        return getEmailServerConfig(email);
    }

    /**
     * 验证邮箱服务器连接
     *
     * @param email         邮箱地址
     * @param authCode      授权码/密码
     * @param config        邮箱服务器配置
     * @param emailProvider 邮箱发行商标识
     * @return 验证结果
     * @throws MessagingException 如果连接或认证失败
     */
    private boolean verifyMailServerConnection(String email, String authCode, EmailServerConfig config, String emailProvider) throws MessagingException {
        // 创建独立的JavaMailSenderImpl实例，不依赖全局配置
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        mailSender.setHost(config.getHost());
        mailSender.setPort(config.getPort());
        mailSender.setUsername(email);
        mailSender.setPassword(authCode);

        // 配置属性
        Properties props = mailSender.getJavaMailProperties();
        props.put("mail.smtp.auth", "true");

        // 增加超时时间
        props.put("mail.smtp.connectiontimeout", "30000"); // 30秒
        props.put("mail.smtp.timeout", "30000");
        props.put("mail.smtp.writetimeout", "30000");

        // 禁用DNS查询缓存
        props.put("networkaddress.cache.ttl", "0");
        props.put("networkaddress.cache.negative.ttl", "0");

        // 直接连接，不使用代理
        props.put("mail.smtp.localhost", "localhost");
        props.put("mail.smtp.localaddress", "0.0.0.0");

        // 根据邮箱发行商设置特定配置
        if ("163".equals(emailProvider) || "126".equals(emailProvider) || EMAIL_163.matcher(email).matches() || EMAIL_126.matcher(email).matches()) {
            // 163和126邮箱需要设置mail.smtp.noop.strict=false
            props.put("mail.smtp.noop.strict", "false");
            // 增加163邮箱的连接稳定性
            props.put("mail.smtp.ssl.protocols", "TLSv1.2 TLSv1.1 TLSv1 SSLv3");
            props.put("mail.smtp.ssl.ciphersuites", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA TLS_RSA_WITH_AES_128_CBC_SHA");
        }

        // Gmail邮箱特殊配置
        if ("gmail".equals(emailProvider) || EMAIL_GMAIL.matcher(email).matches()) {
            // Gmail需要更严格的安全设置
            props.put("mail.smtp.ssl.trust", "smtp.gmail.com");
            props.put("mail.smtp.ssl.checkserveridentity", "true");

            // 特别针对587端口的TLS配置
            if (config.getPort() == 587 && config.isStartTlsEnable()) {
                log.info("使用Gmail端口587的TLS配置");
                // 明确指定TLS版本
                props.put("mail.smtp.ssl.protocols", "TLSv1.2 TLSv1.3");
                props.put("mail.smtp.starttls.enable", "true");
                props.put("mail.smtp.starttls.required", "true");
            } else {
                props.put("mail.smtp.ssl.protocols", "TLSv1.2");
            }

            // 如果授权码看起来像OAuth2 token (长度超过30且包含特定字符)
            if (authCode != null && authCode.length() > 30 && authCode.contains(".") && authCode.contains("-")) {
                log.info("检测到可能的OAuth2令牌，尝试使用XOAUTH2认证");
                props.put("mail.smtp.auth.mechanisms", "XOAUTH2");
            } else {
                log.info("使用应用专用密码进行Gmail验证");
                // 使用应用专用密码时的配置
                props.put("mail.smtp.auth.mechanisms", "LOGIN PLAIN");
            }

            // Gmail的连接超时可能需要更长时间
            props.put("mail.smtp.connectiontimeout", "15000"); // 15秒，与用户提供的配置一致
            props.put("mail.smtp.timeout", "15000");
        }

        // 新浪邮箱特殊配置
        if ("sina".equals(emailProvider) || EMAIL_SINA.matcher(email).matches()) {
            // 新浪邮箱需要设置mail.smtp.noop.strict=false
            props.put("mail.smtp.noop.strict", "false");
            // 新浪邮箱支持的SSL协议
            props.put("mail.smtp.ssl.protocols", "TLSv1.2 TLSv1.1 TLSv1 SSLv3");
            // 新浪邮箱可能需要更长的超时时间
            props.put("mail.smtp.connectiontimeout", "45000"); // 45秒
            props.put("mail.smtp.timeout", "45000");
            // 新浪邮箱的认证机制
            props.put("mail.smtp.auth.mechanisms", "LOGIN PLAIN");
        }

        // Yahoo邮箱特殊配置
        if ("yahoo".equals(emailProvider) || EMAIL_YAHOO.matcher(email).matches()) {
            props.put("mail.smtp.ssl.protocols", "TLSv1.2 TLSv1.3");
            props.put("mail.smtp.ssl.trust", "smtp.mail.yahoo.com");
            props.put("mail.smtp.connectiontimeout", "45000"); // 45秒
            props.put("mail.smtp.timeout", "45000");
        }

        // Outlook邮箱特殊配置
        if ("outlook".equals(emailProvider) || EMAIL_OUTLOOK.matcher(email).matches()) {
            // 检查是否是OAuth认证方式
            if (authCode != null && authCode.startsWith("{") && authCode.contains("clientId")) {
                try {
                    // 解析JSON格式的OAuth信息
                    log.info("检测到Outlook OAuth认证信息，使用OAuth方式验证");

                    // 这里仅记录OAuth信息，实际的OAuth认证需要更复杂的实现
                    props.put("mail.smtp.auth.mechanisms", "XOAUTH2");
                    props.put("mail.smtp.auth.xoauth2.disable", "false");

                    // 设置其他OAuth相关属性
                    props.put("mail.smtp.ssl.protocols", "TLSv1.2");
                    props.put("mail.smtp.starttls.enable", "true");
                    props.put("mail.smtp.starttls.required", "true");
                    props.put("mail.smtp.ssl.trust", "smtp.office365.com");

                    // 记录OAuth认证信息，但不打印敏感信息
                    log.info("Outlook OAuth认证信息已设置");
                } catch (Exception e) {
                    log.error("解析Outlook OAuth信息失败: {}", e.getMessage());
                }
            } else {
                // 常规密码认证
                props.put("mail.smtp.ssl.protocols", "TLSv1.2");
                props.put("mail.smtp.starttls.enable", "true");
                props.put("mail.smtp.starttls.required", "true");
                props.put("mail.smtp.ssl.trust", "smtp.office365.com");
            }
        }

        // SSL配置
        if (config.isSslEnable()) {
            props.put("mail.smtp.ssl.enable", "true");
            props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            props.put("mail.smtp.socketFactory.port", String.valueOf(config.getPort()));
            props.put("mail.smtp.ssl.trust", config.getHost());
            props.put("mail.smtp.ssl.protocols", "TLSv1.2");
        }

        // STARTTLS配置
        if (config.isStartTlsEnable()) {
            props.put("mail.smtp.starttls.enable", "true");
            props.put("mail.smtp.starttls.required", "true");
            props.put("mail.smtp.ssl.trust", config.getHost());
            props.put("mail.smtp.ssl.protocols", "TLSv1.2");
        }

        // 启用调试模式
        props.put("mail.debug", "true");

        // 尝试连接
        try {
            // 获取会话
            Session session = Session.getInstance(props);
            session.setDebug(true);

            Transport transport = session.getTransport("smtp");

            // 连接服务器
            transport.connect(config.getHost(), email, authCode);
            boolean connected = transport.isConnected();

            // 关闭连接
            transport.close();

            return connected;
        } catch (AuthenticationFailedException e) {
            log.error("邮箱验证失败: {}", e.getMessage());
            throw e;
        } catch (MessagingException e) {
            log.error("连接邮箱服务器失败: {}", e.getMessage());
            throw e;
        }
    }

    /**
     * 测试Socket连接
     *
     * @param host    主机名
     * @param port    端口
     * @param timeout 超时时间 (毫秒)
     * @return 连接成功返回true，失败返回false
     */
    private boolean testSocketConnection(String host, int port, int timeout) {
        Socket socket = null;
        try {
            socket = new Socket();
            InetSocketAddress address = new InetSocketAddress(host, port);
            socket.connect(address, timeout);
            return true;
        } catch (IOException e) {
            log.warn("Socket连接失败: {}:{}, 错误: {}", host, port, e.getMessage());
            return false;
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    log.error("关闭Socket失败: {}", e.getMessage());
                }
            }
        }
    }

    /**
     * 内部类：邮箱服务器配置
     */
    private static class EmailServerConfig {
        private final String host;
        private final int port;
        private final boolean startTlsEnable;
        private final boolean sslEnable;

        public EmailServerConfig(String host, int port, boolean startTlsEnable, boolean sslEnable) {
            this.host = host;
            this.port = port;
            this.startTlsEnable = startTlsEnable;
            this.sslEnable = sslEnable;
        }

        public String getHost() {
            return host;
        }

        public int getPort() {
            return port;
        }

        public boolean isStartTlsEnable() {
            return startTlsEnable;
        }

        public boolean isSslEnable() {
            return sslEnable;
        }
    }
} 